﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using Kugar.Core.ExtMethod;
using Kugar.UI.Web.AdminLTE.Enums;
using Kugar.UI.Web.AdminLTE.Helpers;
using Microsoft.AspNetCore.Mvc.Rendering;
using Newtonsoft.Json.Linq;

namespace Kugar.UI.Web.AdminLTE.PageControls.PageForms
{
    /// <summary>
    /// 城市选择框,并允许选择是否加多一个地址输入框
    /// </summary>
    /// <remarks>
    /// 对应的编号使用国家标准的编号,具体可以参见 http://ip.bczs.net/diming
    /// </remarks>
    public class PageForm_CityPicker: PageForm_InputFieldBase
    {
        private static Lazy<Dictionary<string, string>> _cacheCityCodes =null;
        private bool _withAddressBox = false;
        private string _addressBoxName = "";
        private string _addressBoxValue = "";
        private string _addressBoxPlaceholder = "";
        private bool _addressBoxReadonly = false;
        private string _value = "";
        private string _placeholder = "请选择";
        private CityPickerLevelEnum _level = CityPickerLevelEnum.all;
        //private bool _disabled = false;
        private string _cityPickerName = "";
        private bool _readonly = false;

        static PageForm_CityPicker()
        {
            _cacheCityCodes = new Lazy<Dictionary<string, string>>(decodeCity);
        }

        public PageForm_CityPicker(PageForm_Form form, ViewContext viewContext) : base(form, viewContext)
        {
            this.Css("webui-form_citypickerfield citypicker");

            this.AdminLTEUI.PluginUsaged.CityPicker = true;
        }

        public PageForm_CityPicker Name(string name)
        {
            _cityPickerName = name;

            return this;
        }

        /// <summary>
        /// 除了省市选择框之外,再加一个地址输入框
        /// </summary>
        /// <param name="name">地址框的</param>
        /// <param name="value">地址栏的默认值</param>
        /// <returns></returns>
        public PageForm_CityPicker WithAddressBox(string name, string value,string placeholder="",bool @readonly=false)
        {
            _withAddressBox = true;
            _addressBoxName = name;
            _addressBoxValue = value;
            _addressBoxPlaceholder = placeholder;
            _addressBoxReadonly = @readonly;

            return this;

        }

        /// <summary>
        /// 按code设置控件对应的选项
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public PageForm_CityPicker ValueByCode(string code)
        {
            if (_cacheCityCodes.Value.TryGetValue(code.ToStringEx(), out var fullName))
            {
                ValueByName(fullName);
            }
            else
            {
                //throw new ArgumentOutOfRangeException(nameof(code),$"{code}不存在");
                ValueByName("");
            }

            return this;
        }

        /// <summary>
        /// 初始化的值,以/分隔,注意,这里输入的是省市区的名字,不是代码
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public PageForm_CityPicker ValueByName(string value)
        {
            _value = value;

            return this;
        }

        /// <summary>
        /// 初始化的值,注意,这里输入的是省市区的名字,不是代码
        /// </summary>
        /// <param name="province"></param>
        /// <param name="city"></param>
        /// <param name="district"></param>
        /// <returns></returns>
        public PageForm_CityPicker ValueByName(string province, string city, string district="")
        {
            return ValueByName($"{province}/{city}/{district}");
        }

        public PageForm_CityPicker Placeholder(string placeholder)
        {
            _placeholder = placeholder;
            return this;
        }

        public PageForm_CityPicker ReadOnly(bool @readonly = true)
        {
            _readonly = @readonly;

            return this;
        }

        public PageForm_CityPicker Required (bool allRequired = true)
        {
            _isRequired = allRequired;

            return this;
        }

        /// <summary>
        /// 最大选择的层级
        /// </summary>
        /// <param name=""></param>
        /// <returns></returns>
        public PageForm_CityPicker Level(CityPickerLevelEnum level=CityPickerLevelEnum.all)
        {
            _level = level;

            return this;
        }

        protected override void BeforeRender(TextWriter writer)
        {
            if (_withAddressBox)
            {
                this.Css("withaddressbox");
            }

            this.Data("level", _level.ToStringEx());

            base.BeforeRender(writer);
        }

        protected override void RenderContent(TextWriter writer)
        {
            /*
             <div data-toggle="city-picker">
               <input readonly type="text" data-toggle="city-picker" >
            </div>
             */

            //writer.WriteLine("<div class=\"city-picker\">");

            //writer.WriteLine($"<input type=\"{_type}\" name=\"{_startName}\" value=\"{_startValue}\" max=\"{_maxValue}\" min=\"{_minValue}\" class=\"form-control\" placeholder=\"{_startPlaceHolder}\">");
            //writer.WriteLine("<span class=\"input-group-addon\">-</span>");
            //writer.WriteLine($"<input type=\"{_type}\" name=\"{_endName}\" value=\"{_endValue}\" max=\"{_maxValue}\" min=\"{_minValue}\" class=\"form-control\" placeholder=\"{_endPlaceHolder}\">");

            //ViewContext.Writer.WriteLine("<div style=\"position: relative;\"><!-- container -->");
            writer.WriteLine($"<input class=\"citypickertextbox form-control\" {_readonly.If("readonly")} {_isRequired.If("required")}  placeholder=\"{_placeholder}\" type=\"text\" name=\"{_cityPickerName}\" value=\"{_value}\" {(_isRequired?"required":"")}/>");

            writer.WriteLine($"<input type=\"hidden\" class=\"provincecode\" name=\"{_cityPickerName}_ProvinceCode\" />");
            writer.WriteLine($"<input type=\"hidden\" class=\"citycode\" name=\"{_cityPickerName}_CityCode\" />");
            writer.WriteLine($"<input type=\"hidden\" class=\"districtcode\" name=\"{_cityPickerName}_DistrictCode\" />");


            //ViewContext.Writer.WriteLine("</div>");
            if (_withAddressBox)
            {
                writer.WriteLine($"<input class=\"addressboxtextbox form-control\" {_isRequired.If("required")} {(_addressBoxReadonly).If("readonly")} placeholder=\"{_addressBoxPlaceholder}\" type=\"text\"  {(_isRequired ? "required" : "")} name=\"{_addressBoxName}\" value=\"{_addressBoxValue}\" />");

            }

            //writer.WriteLine("</div>");
        }

        protected override string ErrorMessage
        {
            get
            {
                return GetErrorMessageByNames(_addressBoxName, _cityPickerName);

                var errorMsg = "";

                if (ViewContext.ModelState.TryGetValue(_cityPickerName, out var error)) // ModelMetadata.FromStringExpression(_name, ViewContext.ViewData);
                {
                    errorMsg= error.Errors.Select(x => x.ErrorMessage).JoinToString('|');
                }

                if (ViewContext.ModelState.TryGetValue(_addressBoxName, out var error1))
                {
                    errorMsg += error1.Errors.Select(x => x.ErrorMessage).JoinToString('|');
                }

                return errorMsg.Trim('|');

            }
        }

        protected override bool HasError => IsHasErrorByNames(_cityPickerName, _addressBoxName);


        private static Dictionary<string, string> decodeCity()
        {
            var assembly = typeof(AdminLTEUI).Assembly;
            var resourceName = "Kugar.UI.Web.AdminLTE.Content.city.min.json";

            var result = "";

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }

            var data = JArray.Parse(result);

            var fullName=new Dictionary<string,string>();
            
            foreach (JObject province in data)
            {
                fullName.Add(province.GetString("code").PadRight(6, '0'), province.GetString("name"));

                var citylist = province.GetJObjectArray("sub");

                foreach (var city in citylist)
                {
                    fullName.Add(city.GetString("code").PadRight(6, '0'),
                        (province.GetString("name") == city.GetString("name")) ? city.GetString("name") : $"{province.GetString("name")}/{city.GetString("name")}"
                        );

                    foreach (var district in city.GetJObjectArray("sub"))
                    {
                        var parentFullName = (province.GetString("name") == city.GetString("name"))
                            ? city.GetString("name")
                            : $"{province.GetString("name")}/{city.GetString("name")}";

                        fullName.Add(district.GetString("code").PadRight(6, '0'),
                            $"{parentFullName}/{district.GetString("name")}"
                        );

                    }
                }
            }

            return fullName;
        }
    }
}
